<template>
    <div class="datepicker" :class="{'datepicker-range':range,'datepicker__clearable':clearable&&text&&!disabled,['datepicker-'+size]:size}">
        <input readonly :value="text" :class="[show ? 'focus' : '', inputClass]" :disabled="disabled" :placeholder="placeholder" :name="name" v-if="type!=='inline'" ref="input" />
        <a class="datepicker-close" @click.stop="cls"></a>
        <transition name="datepicker-zoom-in-top">
            <div class="datepicker-popup" :class="[popupClass,{'datepicker-inline':type==='inline'},{'datepicker-popup-range':range}]" tabindex="-1" v-if="show||type==='inline'" ref="popup">
                <template v-if="range">
                    <vue-datepicker-local-calendar v-model="dates[0]" :left="true"></vue-datepicker-local-calendar>
                    <vue-datepicker-local-calendar v-model="dates[1]" :right="true"></vue-datepicker-local-calendar>
                </template>
                <template v-else>
                    <vue-datepicker-local-calendar v-model="dates[0]"></vue-datepicker-local-calendar>
                </template>
                <div v-if="showButtons" class="datepicker__buttons">
                    <mj-button @click.prevent.stop.native="cancel" size="small" class="datepicker__button-cancel">{{this.local.cancelTip}}</mj-button>
                    <mj-button @click.prevent.stop.native="submit" type="primary" size="small" class="datepicker__button-select">{{this.local.submitTip}}</mj-button>
                </div>
            </div>
        </transition>
    </div>
</template>

<script>
import { prefixCls } from '../prefix'
import VueDatepickerLocalCalendar from './VueDatepickerLocalCalendar.vue'

export default {
    name: `${prefixCls}Datepicker`,
    components: { VueDatepickerLocalCalendar },
    props: {
        name: [String],
        inputClass: [String],
        popupClass: [String],
        value: [Date, Array, String],
        disabled: [Boolean],
        type: {
            type: String,
            default: 'normal'
        },
        rangeSeparator: {
            type: String,
            default: '~'
        },
        clearable: {
            type: Boolean,
            default: false
        },
        placeholder: [String],
        disabledDate: {
            type: Function,
            default: () => {
                return false
            }
        },
        format: {
            type: String,
            default: 'YYYY-MM-DD'
        },
        local: {
            type: Object,
            default () {
                return {
                    dow: 1, // Monday is the first day of the week
                    hourTip: '选择小时', // tip of select hour
                    minuteTip: '选择分钟', // tip of select minute
                    secondTip: '选择秒数', // tip of select second
                    yearSuffix: '年', // format of head
                    monthsHead: '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'), // months of head
                    months: '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'), // months of panel
                    weeks: '一_二_三_四_五_六_日'.split('_'), // weeks
                    cancelTip: '取消', // default text for cancel button
                    submitTip: '确定' // default text for submit button
                }
            }
        },
        showButtons: {
            type: Boolean,
            default: false
        },
        dateRangeSelect: [Function],
        transfer:{//弹层放置于body内
            type:Boolean,
            default:false
        },
        size: String,
    },
    data () {
        return {
            prefixCls: prefixCls,
            show: false,
            dates: this.vi(this.value)
        }
    },
    computed: {
        range () {
            // console.log('computed range')
            return this.dates.length === 2
        },
        text () {
             // console.log('computed text')
            const val = this.value
            const txt = this.dates.map(date => this.tf(date)).join(` ${this.rangeSeparator} `)
            if (Array.isArray(val)) {
                return val.length > 1 ? txt : ''
            } else {
                return val ? txt : ''
            }
        }
    },
    watch: {
        value (val) {
            // console.log('watch value：',val)
            this.dates = this.vi(this.value)
        }
    },
    methods: {
        get () {
            return Array.isArray(this.value) ? this.dates : this.dates[0]
        },
        cls () {
            this.$emit('clear')
            this.$emit('input', this.range ? [] : '')
        },
        vi (val) {
            if (Array.isArray(val)) {
                return val.length > 1 ? val.map(item => new Date(item)) : [new Date(), this.nextMonth()]
            } else {
                return val ? new Array(new Date(val)) : [new Date()]
            }
        },
        nextMonth(){
            var nowdate = new Date();
            nowdate.setMonth(nowdate.getMonth()+1);
            return nowdate
        },
        ok (leaveOpened) {
            const $this = this
            // console.log('ok',$this.range)
            $this.$emit('input', $this.get())
            !leaveOpened && !$this.showButtons && setTimeout(() => {
                $this.show = $this.range
            })
        },
        tf (time, format) {
            const year = time.getFullYear()
            const month = time.getMonth()
            const day = time.getDate()
            const hours24 = time.getHours()
            const hours = hours24 % 12 === 0 ? 12 : hours24 % 12
            const minutes = time.getMinutes()
            const seconds = time.getSeconds()
            const milliseconds = time.getMilliseconds()
            const dd = t => ('0' + t).slice(-2)
            const map = {
                YYYY: year,
                MM: dd(month + 1),
                MMM: this.local.months[month],
                MMMM: this.local.monthsHead[month],
                M: month + 1,
                DD: dd(day),
                D: day,
                HH: dd(hours24),
                H: hours24,
                hh: dd(hours),
                h: hours,
                mm: dd(minutes),
                m: minutes,
                ss: dd(seconds),
                s: seconds,
                S: milliseconds
            }
            return (format || this.format).replace(/Y+|M+|D+|H+|h+|m+|s+|S+/g, str => map[str])
        },
        dc (e) {
            this.show = this.$el.contains(e.target) && !this.disabled
        },
        submit () {
            // console.log('submit')
            this.$emit('confirm', this.get())
            this.show = false
        },
        cancel () {
            // console.log('cancel')
            this.$emit('cancel')
            this.show = false
        },
        _showHide(e){
            if(this.$refs.popup && this.$refs.popup.contains(e.target)) {
                return false
            }
            if (this.$el.contains(e.target)) {
                this.disabled == false ? this.show = !this.show : "";

                if(this.transfer && this.show){
                    const body = document.querySelector("body");
                    this.$nextTick(()=> {
                        if (body.append) {
                            body.append(this.$refs.popup);
                        } else {
                            body.appendChild(this.$refs.popup);
                        }
                        this.setPosition(this.$refs.popup)
                    });
                    this.setPosition(this.$refs.popup)
                }else{
                    this.$nextTick(()=> {
                        this.show?this.setPosition(this.$refs.popup) : "";
                    })
                }
            }else{
                this.show = false;
            }
        },
        setPosition(dp){
            if(dp) {
                // 位置定位
                const DOMRect1 = this.$refs.input.getBoundingClientRect(),
                      DOMRect2 = dp.getBoundingClientRect();
                const _l1 = DOMRect1.left,
                      _t1 = DOMRect1.top,
                      _w1 = DOMRect1.width,
                      _w2 = DOMRect2.width,
                      _h1 = DOMRect1.height,
                      _h2 = dp.offsetHeight, //下拉层高度,这个算出来准
                      _t2 = DOMRect2.top,
                      _st = window.pageYOffset, //滚动高度
                      _ch = document.documentElement.clientHeight, //浏览器可视化窗口的大小  
                      _ww = window.innerWidth; //浏览器内宽
                // 处理下拉层宽度太大，超出右侧屏幕。当超出时，右侧对齐边缘
                if(_ww < (_w2 + _l1)) {
                  dp.style.marginLeft = -(_w2+_l1-_ww+17)+'px';
                }
                if(this.transfer){
                    if (Number(_t1+_h1+_h2) > _ch) {
                        dp.setAttribute('position', 'top');
                        dp.style.top = (_t1-_h2+_st-4)+'px';
                        dp.style.left = _l1+'px';
                        dp.style.transformOrigin = 'center bottom';
                    }else{
                        dp.removeAttribute("position");
                        dp.style.top = (_t1+_h1+_st)+'px';
                        dp.style.left = _l1+'px';
                    }
                }else{
                    if (Number(_t1+_h1+_h2) > _ch) {
                        dp.setAttribute('position', 'top');
                        dp.style.marginTop = '-'+Number(_h1+_h2)+'px';
                        dp.style.transformOrigin = 'center bottom';
                    }else{
                        dp.removeAttribute("position");
                        dp.style.marginTop = '';
                    }
                }
            }
        },
    },
    mounted () {
        document.addEventListener('click', this._showHide,true);
    },
    beforeDestroy () {
        document.removeEventListener('click', this.dc,true)
    }
}
</script>